//----------------------------------------------------------------------------
//
// TSDuck - The MPEG Transport Stream Toolkit
// Copyright (c) 2005-2022, Thierry Lelegard
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
//----------------------------------------------------------------------------
//
//  TSUnit test suite for ARIB character sets.
//
//----------------------------------------------------------------------------

#include "tsARIBCharset.h"
#include "tsByteBlock.h"
#include "tsSysUtils.h"
#include "tsunit.h"

// The ARIB STD-B24 encoder alternates charset switch from GL and GR.
// Define this if the first charset switch is on GL. Comment it if it's on GR.
#define GL_FIRST 1


//----------------------------------------------------------------------------
// The test fixture
//----------------------------------------------------------------------------

class ARIBCharsetTest: public tsunit::Test
{
public:
    ARIBCharsetTest();
    virtual void beforeTest() override;
    virtual void afterTest() override;

    void testCanEncode();
    void testDecode1();
    void testDecode2();
    void testDecode3();
    void testDecode4();
    void testDecode5();
    void testDecode6();
    void testDecode7();
    void testDecode8();
    void testDecode9();
    void testDecode10();
    void testDecode11();
    void testDecode12();
    void testDecode13();
    void testDecode14();
    void testDecode15();
    void testDecode16();
    void testDecode17();
    void testDecode18();
    void testDecode19();
    void testDecode20();
    void testDecode21();
    void testDecode22();
    void testDecode23();
    void testDecode24();
    void testDecode25();
    void testDecode26();
    void testEncode1();
    void testEncode2();
    void testEncode3();
    void testEncode4();
    void testEncode5();
    void testEncode6();
    void testEncode7();
    void testEncode8();
    void testEncode9();
    void testEncode10();
    void testEncode11();
    void testEncode12();
    void testEncode13();
    void testEncode14();
    void testEncode15();
    void testEncode16();
    void testEncode17();
    void testEncode18();
    void testEncode19();
    void testEncode20();
    void testEncode21();
    void testEncode22();
    void testEncode23();
    void testEncode24();
    void testEncode25();

    TSUNIT_TEST_BEGIN(ARIBCharsetTest);
    TSUNIT_TEST(testCanEncode);
    TSUNIT_TEST(testDecode1);
    TSUNIT_TEST(testDecode2);
    TSUNIT_TEST(testDecode3);
    TSUNIT_TEST(testDecode4);
    TSUNIT_TEST(testDecode5);
    TSUNIT_TEST(testDecode6);
    TSUNIT_TEST(testDecode7);
    TSUNIT_TEST(testDecode8);
    TSUNIT_TEST(testDecode9);
    TSUNIT_TEST(testDecode10);
    TSUNIT_TEST(testDecode11);
    TSUNIT_TEST(testDecode12);
    TSUNIT_TEST(testDecode13);
    TSUNIT_TEST(testDecode14);
    TSUNIT_TEST(testDecode15);
    TSUNIT_TEST(testDecode16);
    TSUNIT_TEST(testDecode17);
    TSUNIT_TEST(testDecode18);
    TSUNIT_TEST(testDecode19);
    TSUNIT_TEST(testDecode20);
    TSUNIT_TEST(testDecode21);
    TSUNIT_TEST(testDecode22);
    TSUNIT_TEST(testDecode23);
    TSUNIT_TEST(testDecode24);
    TSUNIT_TEST(testDecode25);
    TSUNIT_TEST(testDecode26);
    TSUNIT_TEST(testEncode1);
    TSUNIT_TEST(testEncode2);
    TSUNIT_TEST(testEncode3);
    TSUNIT_TEST(testEncode4);
    TSUNIT_TEST(testEncode5);
    TSUNIT_TEST(testEncode6);
    TSUNIT_TEST(testEncode7);
    TSUNIT_TEST(testEncode8);
    TSUNIT_TEST(testEncode9);
    TSUNIT_TEST(testEncode10);
    TSUNIT_TEST(testEncode11);
    TSUNIT_TEST(testEncode12);
    TSUNIT_TEST(testEncode13);
    TSUNIT_TEST(testEncode14);
    TSUNIT_TEST(testEncode15);
    TSUNIT_TEST(testEncode16);
    TSUNIT_TEST(testEncode17);
    TSUNIT_TEST(testEncode18);
    TSUNIT_TEST(testEncode19);
    TSUNIT_TEST(testEncode20);
    TSUNIT_TEST(testEncode21);
    TSUNIT_TEST(testEncode22);
    TSUNIT_TEST(testEncode23);
    TSUNIT_TEST(testEncode24);
    TSUNIT_TEST(testEncode25);
    TSUNIT_TEST_END();

private:
    const bool _cSyntaxDebug;
    void dump(const ts::UString& title, const ts::ByteBlock& bb);
    void dump(const ts::UString& title, const ts::UString& str);
};

TSUNIT_REGISTER(ARIBCharsetTest);


//----------------------------------------------------------------------------
// Initialization.
//----------------------------------------------------------------------------

// Constructor.
ARIBCharsetTest::ARIBCharsetTest() :
    _cSyntaxDebug(!ts::GetEnvironment(u"TS_UTEST_ARIB_CSYNTAX").empty())
{
}

// Test suite initialization method.
void ARIBCharsetTest::beforeTest()
{
}

// Test suite cleanup method.
void ARIBCharsetTest::afterTest()
{
}


//----------------------------------------------------------------------------
// Dump routines in debug mode.
//----------------------------------------------------------------------------

void ARIBCharsetTest::dump(const ts::UString& title, const ts::ByteBlock& bb)
{
    if (debugMode()) {
        debug() << title.toJustifiedLeft(10) << ts::UString::Dump(bb, ts::UString::SINGLE_LINE | (_cSyntaxDebug ? ts::UString::C_STYLE : 0)) << std::endl;
    }
}

void ARIBCharsetTest::dump(const ts::UString& title, const ts::UString& str)
{
    if (debugMode()) {
        debug() << title.toJustifiedLeft(10) << '"' << str << '"' << std::endl << "UTF-16:  ";
        for (size_t i = 0; i < str.size(); ++i) {
            debug() << ts::UString::Format(u" %s%X%s", {_cSyntaxDebug ? u"0x" : u"", uint16_t(str[i]), _cSyntaxDebug ? u"," : u""});
        }
        debug() << std::endl;
    }
}


//----------------------------------------------------------------------------
// Test cases
//----------------------------------------------------------------------------

void ARIBCharsetTest::testCanEncode()
{
    const ts::Charset& cset(ts::ARIBCharset::B24);

    TSUNIT_ASSERT(cset.canEncode(u""));
    TSUNIT_ASSERT(cset.canEncode(u"alpha num 09"));
    TSUNIT_ASSERT(cset.canEncode(ts::UString({u'a', u'b'})));
    TSUNIT_ASSERT(!cset.canEncode(ts::UString({u'a', ts::LATIN_SMALL_LETTER_A_WITH_ACUTE, u'b'})));
    TSUNIT_ASSERT(cset.canEncode(ts::UString({0x004E, 0x0048, 0x004B, 0x7DCF, 0x5408, 0x0031, 0x30FB, 0x79CB, 0x7530})));
    TSUNIT_ASSERT(cset.canEncode(ts::UString({0x004E, 0x30E5, 0x30FC, 0xD83C, 0xDE14, 0xD83C, 0xDE11, 0x7DCF})));
    TSUNIT_ASSERT(!cset.canEncode(ts::UString({0x004E, 0x30E5, 0x30FC, 0xDBFF, 0xDFFF, 0xD83C, 0xDE11, 0x7DCF})));
}


//----------------------------------------------------------------------------
// Decode test cases
//----------------------------------------------------------------------------

#define B(...) const ts::ByteBlock b24({__VA_ARGS__})
#define U(...) const ts::UString   u16({__VA_ARGS__})
#define T(success)             \
    debug() << std::endl;      \
    dump(u"Input:", b24);      \
    ts::UString dec;           \
    const bool ok = ts::ARIBCharset::B24.decode(dec, b24.data(), b24.size()); \
    dump(u"Decoded:", dec);    \
    dump(u"Expected:", u16);   \
    debug() << std::endl;      \
    TSUNIT_EQUAL(success, ok); \
    TSUNIT_EQUAL(u16, dec)


void ARIBCharsetTest::testDecode1()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x41, 0x6D, 0x39, 0x67, 0x0E, 0x31, 0xFE, 0x0F, 0x3D, 0x29, 0x45, 0x44);
    U(0x004E, 0x0048, 0x004B, 0x7DCF, 0x5408, 0x0031, 0x30FB, 0x79CB, 0x7530);
    T(true);
}

void ARIBCharsetTest::testDecode2()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x41, 0x6D, 0x39, 0x67, 0x0E, 0x32, 0xFE, 0x0F, 0x3D, 0x29, 0x45, 0x44);
    U(0x004E, 0x0048, 0x004B, 0x7DCF, 0x5408, 0x0032, 0x30FB, 0x79CB, 0x7530);
    T(true);
}

void ARIBCharsetTest::testDecode3()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x37, 0x48, 0x42, 0x53, 0x0E, 0x47, 0xFE, 0x0F, 0x3D, 0x29, 0x45, 0x44);
    U(0x004E, 0x0048, 0x004B, 0x643A, 0x5E2F, 0x0047, 0x30FB, 0x79CB, 0x7530);
    T(true);
}

void ARIBCharsetTest::testDecode4()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x45, 0x1D, 0x46, 0x1D, 0x6C, 0x31, 0x0F, 0x3D, 0x29, 0x45, 0x44);
    U(0x004E, 0x0048, 0x004B, 0x0045, 0x30C6, 0x30EC, 0x0031, 0x79CB, 0x7530);
    T(true);
}

void ARIBCharsetTest::testDecode5()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x45, 0x1D, 0x46, 0x1D, 0x6C, 0x32, 0x0F, 0x3D, 0x29, 0x45, 0x44);
    U(0x004E, 0x0048, 0x004B, 0x0045, 0x30C6, 0x30EC, 0x0032, 0x79CB, 0x7530);
    T(true);
}

void ARIBCharsetTest::testDecode6()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x45, 0x1D, 0x46, 0x1D, 0x6C, 0x33, 0x0F, 0x3D, 0x29, 0x45, 0x44);
    U(0x004E, 0x0048, 0x004B, 0x0045, 0x30C6, 0x30EC, 0x0033, 0x79CB, 0x7530);
    T(true);
}

void ARIBCharsetTest::testDecode7()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x37, 0x48, 0x42, 0x53, 0x0E, 0x32);
    U(0x004E, 0x0048, 0x004B, 0x643A, 0x5E2F, 0x0032);
    T(true);
}

void ARIBCharsetTest::testDecode8()
{
    B(0x3D, 0x29, 0x45, 0x44, 0x44, 0x2B, 0x46, 0x7C, 0x4A, 0x7C, 0x41, 0x77);
    U(0x79CB, 0x7530, 0x671D, 0x65E5, 0x653E, 0x9001);
    T(true);
}

void ARIBCharsetTest::testDecode9()
{
    B(0x0E, 0x41, 0x42, 0x53, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x0E, 0x31);
    U(0x0041, 0x0042, 0x0053, 0x79CB, 0x7530, 0x653E, 0x9001, 0x0031);
    T(true);
}

void ARIBCharsetTest::testDecode10()
{
    B(0x0E, 0x41, 0x42, 0x53, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x0E, 0x32);
    U(0x0041, 0x0042, 0x0053, 0x79CB, 0x7530, 0x653E, 0x9001, 0x0032);
    T(true);
}

void ARIBCharsetTest::testDecode11()
{
    B(0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x37, 0x48, 0x42, 0x53);
    U(0x79CB, 0x7530, 0x653E, 0x9001, 0x643A, 0x5E2F);
    T(true);
}

void ARIBCharsetTest::testDecode12()
{
    B(0x0E, 0x41, 0x42, 0x53, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x4E, 0x57, 0x3B, 0x7E);
    U(0x0041, 0x0042, 0x0053, 0x79CB, 0x7530, 0x653E, 0x9001, 0x81E8, 0x6642);
    T(true);
}

void ARIBCharsetTest::testDecode13()
{
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x1B, 0x7C, 0xC6, 0xEC, 0xD3, 0x0E, 0x31);
    U(0x0041, 0x004B, 0x0054, 0x79CB, 0x7530, 0x30C6, 0x30EC, 0x30D3, 0x0031);
    T(true);
}

void ARIBCharsetTest::testDecode14()
{
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x1B, 0x7C, 0xC6, 0xEC, 0xD3, 0x0E, 0x32);
    U(0x0041, 0x004B, 0x0054, 0x79CB, 0x7530, 0x30C6, 0x30EC, 0x30D3, 0x0032);
    T(true);
}

void ARIBCharsetTest::testDecode15()
{
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x4E, 0x57, 0x3B, 0x7E);
    U(0x0041, 0x004B, 0x0054, 0x81E8, 0x6642);
    T(true);
}

void ARIBCharsetTest::testDecode16()
{
    B(0x0E, 0x47, 0x1B, 0x7C, 0xAC, 0xA4, 0xC9);
    U(0x0047, 0x30AC, 0x30A4, 0x30C9);
    T(true);
}

void ARIBCharsetTest::testDecode17()
{
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x1B, 0x7C, 0xC6, 0xEC, 0xD3);
    U(0x0041, 0x004B, 0x0054, 0x79CB, 0x7530, 0x30C6, 0x30EC, 0x30D3);
    T(true);
}

void ARIBCharsetTest::testDecode18()
{
    B(0x0E, 0x4E, 0x48, 0x4B, 0x1D, 0x4B, 0x1D, 0x65, 0xF9, 0x1D, 0x39, 0x37, 0x0F, 0x1B, 0x24, 0x3B, 0x7A, 0x5A, 0x7A, 0x56);
    U(0x004E, 0x0048, 0x004B, 0x30CB, 0x30E5, 0x30FC, 0x30B9, 0x0037, 0xD83C, 0xDE14, 0xD83C, 0xDE11);
    T(true);
}

void ARIBCharsetTest::testDecode19()
{
    B(0x4C, 0x6B, 0x0E, 0x37, 0x0F, 0x3B, 0x7E, 0xFD, 0xFB, 0x30, 0x6C, 0x4A, 0x62, 0x40, 0x68, 0xD8,
      0xFD, 0x30, 0x6C, 0x4A, 0x62, 0x3F, 0x3C, 0xAF, 0xFC, 0x21, 0x21, 0x3A, 0x23, 0xFD, 0xB3, 0xCE,
      0x1D, 0x4B, 0x1D, 0x65, 0xF9, 0x1D, 0x39, 0xF2, 0x46, 0x4F, 0xB1, 0xBF, 0xA4, 0x21, 0x21, 0x21,
      0x5A, 0x1B, 0x7C, 0xAD, 0xE3, 0xB9, 0xBF, 0xF9, 0x21, 0x5B, 0x40, 0x44, 0x30, 0x66, 0x3C, 0x42,
      0x21, 0x24, 0x21, 0x5A, 0xB5, 0xD6, 0xAD, 0xE3, 0xB9, 0xBF, 0xF9, 0x21, 0x5B, 0x43, 0x53, 0x45,
      0x44, 0x3F, 0x2D, 0x3B, 0x52, 0x21, 0x24, 0x30, 0x4B, 0x46, 0x23, 0x33, 0x24, 0x49, 0x27, 0x21,
      0x24, 0x21, 0x5A, 0x35, 0x24, 0x3E, 0x5D, 0xAD, 0xE3, 0xB9, 0xBF, 0xF9, 0x21, 0x5B, 0x43, 0x66,
      0x42, 0x3C, 0x48, 0x7E, 0x38, 0x78);
    U(0x591C, 0x0037, 0x6642, 0x3001, 0x300C, 0x4E00, 0x6B69, 0x5148, 0x3078, 0x3001, 0x4E00, 0x6B69,
      0x6DF1, 0x304F, 0x300D, 0x3000, 0x4ECA, 0x3001, 0x3053, 0x306E, 0x30CB, 0x30E5, 0x30FC, 0x30B9,
      0x3092, 0x5C4A, 0x3051, 0x305F, 0x3044, 0x3000, 0x3010, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC,
      0x3011, 0x9752, 0x4E95, 0x5B9F, 0xFF0C, 0x3010, 0x30B5, 0x30D6, 0x30AD, 0x30E3, 0x30B9, 0x30BF,
      0x30FC, 0x3011, 0x6C60, 0x7530, 0x4F38, 0x5B50, 0xFF0C, 0x4F0A, 0x85E4, 0x6D77, 0x5F66, 0xFF0C,
      0x3010, 0x6C17, 0x8C61, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC, 0x3011, 0x4E2D, 0x6751, 0x7F8E,
      0x516C);
    T(true);
}

void ARIBCharsetTest::testDecode20()
{
    B(0x3D, 0x50, 0x31, 0x69, 0x3C, 0x54);
    U(0x51FA, 0x6F14, 0x8005);
    T(true);
}

void ARIBCharsetTest::testDecode21()
{
    B(0x21, 0x5A, 0x1B, 0x7C, 0xAD, 0xE3, 0xB9, 0xBF, 0xF9, 0x21, 0x5B, 0x40, 0x44, 0x30, 0x66, 0x3C,
      0x42, 0x21, 0x24, 0x21, 0x5A, 0xB5, 0xD6, 0xAD, 0xE3, 0xB9, 0xBF, 0xF9, 0x21, 0x5B, 0x43, 0x53,
      0x45, 0x44, 0x3F, 0x2D, 0x3B, 0x52, 0x21, 0x24, 0x30, 0x4B, 0x46, 0x23, 0x33, 0x24, 0x49, 0x27,
      0x21, 0x24, 0x21, 0x5A, 0x35, 0x24, 0x3E, 0x5D, 0xAD, 0xE3, 0xB9, 0xBF, 0xF9, 0x21, 0x5B, 0x43,
      0x66, 0x42, 0x3C, 0x48, 0x7E, 0x38, 0x78);
    U(0x3010, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC, 0x3011, 0x9752, 0x4E95, 0x5B9F, 0xFF0C, 0x3010,
      0x30B5, 0x30D6, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC, 0x3011, 0x6C60, 0x7530, 0x4F38, 0x5B50,
      0xFF0C, 0x4F0A, 0x85E4, 0x6D77, 0x5F66, 0xFF0C, 0x3010, 0x6C17, 0x8C61, 0x30AD, 0x30E3, 0x30B9,
      0x30BF, 0x30FC, 0x3011, 0x4E2D, 0x6751, 0x7F8E, 0x516C);
    T(true);
}

void ARIBCharsetTest::testDecode22()
{
    B(0x1D, 0x40, 0xF9, 0x1B, 0x6F, 0x26, 0x23, 0x73, 0xAC, 0x0F, 0x4D, 0x68, 0xBF, 0x21, 0x2A, 0xFB,
      0x47, 0x48, 0x4D, 0x70, 0xCE, 0x1B, 0x7C, 0xE9, 0xA4, 0xAA, 0xF3, 0x33, 0x58, 0x31, 0x60, 0x19,
      0x4B, 0x40, 0x78, 0x46, 0x7E, 0x21, 0x2A, 0x49, 0x34, 0x3D, 0x43, 0x19, 0x4E, 0x32, 0x26, 0x19,
      0x72, 0x4D, 0x5C, 0x40, 0x2E, 0x21, 0x2A, 0x21, 0x2A, 0xFC, 0x1B, 0x24, 0x3B, 0x7A, 0x5C, 0x7A,
      0x56);
    U(0x30C0, 0x30FC, 0x30A6, 0x30A3, 0x30F3, 0x304C, 0x6765, 0x305F, 0xFF01, 0x300C, 0x6CE2, 0x4E71,
      0x306E, 0x30E9, 0x30A4, 0x30AA, 0x30F3, 0x5B66, 0x5712, 0x306B, 0x6F5C, 0x5165, 0xFF01, 0x767E,
      0x7363, 0x306E, 0x738B, 0x3092, 0x990A, 0x6210, 0xFF01, 0xFF01, 0x300D, 0xD83C, 0xDE16, 0xD83C,
      0xDE11);
    T(true);
}

void ARIBCharsetTest::testDecode23()
{
    B(0x40, 0x2E, 0x44, 0x39, 0xDE, 0xC3, 0xBF, 0xC0, 0x43, 0x66, 0xCE, 0x1B, 0x6F, 0x69, 0x24, 0x2A,
      0x73, 0xCE, 0x0F, 0x3B, 0x52, 0xC9, 0xE2, 0xBF, 0xC1, 0xAC, 0xFD, 0x37, 0x32, 0xEC, 0xCE, 0x43,
      0x66, 0xC7, 0x40, 0x68, 0x40, 0x38, 0x4C, 0x72, 0xCE, 0x42, 0x67, 0x3F, 0x4D, 0xAB, 0xE9, 0x3C,
      0x6D, 0xEA, 0xCE, 0x35, 0x3B, 0xE4, 0x3B, 0x52, 0x30, 0x69, 0xC6, 0x3D, 0x51, 0xF2, 0x33, 0x58,
      0xD6, 0xFA, 0x49, 0x54, 0x3F, 0x3F, 0x4C, 0x4C, 0x4C, 0x5C, 0xCA, 0x40, 0x38, 0x45, 0x4C, 0xCF,
      0x42, 0x60, 0x33, 0x58, 0x3D, 0x68, 0x4A, 0x2C, 0xCB, 0x21, 0x2A, 0x21, 0x29, 0x33, 0x58, 0x31,
      0x60, 0x1B, 0x7C, 0xC9, 0xE9, 0xDE, 0x34, 0x69, 0x49, 0x69, 0x19, 0x31, 0x19, 0x4E, 0x47, 0x48,
      0x4D, 0x70, 0x19, 0x4E, 0x46, 0x7C, 0x21, 0x39, 0x19, 0x4B, 0x4C, 0x29, 0x43, 0x65, 0x21, 0x2A);
    U(0x6210, 0x9577, 0x307E, 0x3063, 0x305F, 0x3060, 0x4E2D, 0x306E, 0x30E9, 0x30A4, 0x30AA, 0x30F3,
      0x306E, 0x5B50, 0x3069, 0x3082, 0x305F, 0x3061, 0x304C, 0x3001, 0x7FA4, 0x308C, 0x306E, 0x4E2D,
      0x3067, 0x5148, 0x751F, 0x5F79, 0x306E, 0x5927, 0x4EBA, 0x304B, 0x3089, 0x72E9, 0x308A, 0x306E,
      0x6280, 0x3084, 0x5B50, 0x80B2, 0x3066, 0x8853, 0x3092, 0x5B66, 0x3076, 0x3002, 0x4E0D, 0x771F,
      0x9762, 0x76EE, 0x306A, 0x751F, 0x5F92, 0x306F, 0x9000, 0x5B66, 0x51E6, 0x5206, 0x306B, 0xFF01,
      0xFF1F, 0x5B66, 0x5712, 0x30C9, 0x30E9, 0x30DE, 0x9854, 0x8CA0, 0x3051, 0x306E, 0x6CE2, 0x4E71,
      0x306E, 0x65E5, 0x3005, 0x306B, 0x5BC6, 0x7740, 0xFF01);
    T(true);
}

void ARIBCharsetTest::testDecode24()
{
    B(0x21, 0x5A, 0x45, 0x5A, 0x4D, 0x4B, 0x3B, 0x7E, 0x42, 0x65, 0x1B, 0x7C, 0xC9, 0xE9, 0xDE, 0x21,
      0x5B, 0x31, 0x40, 0x4C, 0x38, 0x3F, 0x4E, 0x3A, 0x38, 0x31, 0x52, 0x4C, 0x67, 0x0E, 0x33, 0x0F,
      0x21, 0x21, 0x1B, 0x24, 0x3B, 0x7A, 0x6B, 0x1B, 0x24, 0x39, 0x21, 0x4A, 0x0E, 0x31, 0x0F, 0x21,
      0x4B, 0xFB, 0x4D, 0x72, 0x19, 0x4E, 0x4D, 0x3D, 0x34, 0x36, 0xFC, 0x1B, 0x24, 0x3B, 0x7A, 0x5C,
      0x7A, 0x56);
    U(0x3010, 0x571F, 0x66DC, 0x6642, 0x4EE3, 0x30C9, 0x30E9, 0x30DE, 0x3011, 0x96F2, 0x9727, 0x4EC1,
      0x5DE6, 0x885B, 0x9580, 0x0033, 0x3000, 0xD83C, 0xDE1F, 0xFF08, 0x0031, 0xFF09, 0x300C, 0x5D50,
      0x306E, 0x4E88, 0x611F, 0x300D, 0xD83C, 0xDE16, 0xD83C, 0xDE11);
    T(true);
}

void ARIBCharsetTest::testDecode25()
{
    B(0x1B, 0x7C, 0xCA, 0xCB, 0xB3, 0xEC, 0x44, 0x41, 0x49, 0x34, 0x37, 0x4A, 0x20, 0x40, 0x56, 0x1B,
      0x7D, 0xC1, 0xE3, 0xF3, 0xAC, 0x25, 0x4A, 0x25, 0x5E, 0x25, 0x3A, 0xF2, 0x3F, 0x29, 0xD9, 0xEB,
      0x21, 0x29, 0x44, 0x41, 0x49, 0x77, 0x3D, 0x2C, 0x42, 0x33, 0x21, 0x39, 0x21, 0x75, 0x46, 0x30,
      0x4A, 0x2A, 0xC8, 0x3F, 0x4D, 0xCE, 0x36, 0x43, 0xAD, 0xCE, 0x3B, 0x36, 0x4A, 0x62, 0x0E, 0x53,
      0x50, 0x1B, 0x24, 0x3B, 0x0F, 0x7A, 0x56);
    U(0x30CA, 0x30CB, 0x30B3, 0x30EC, 0x73CD, 0x767E, 0x666F, 0x3000, 0x8D64, 0x3061, 0x3083, 0x3093,
      0x304C, 0x30CA, 0x30DE, 0x30BA, 0x3092, 0x98DF, 0x3079, 0x308B, 0xFF1F, 0x73CD, 0x98A8, 0x7FD2,
      0x7D9A, 0x3005, 0xFF06, 0x52D5, 0x7269, 0x3068, 0x4EBA, 0x306E, 0x9A5A, 0x304D, 0x306E, 0x6563,
      0x6B69, 0x0053, 0x0050, 0xD83C, 0xDE11);
    T(true);
}

void ARIBCharsetTest::testDecode26()
{
    B(0x21, 0x7A, 0x46, 0x7C, 0x4B, 0x5C, 0x41, 0x34, 0x39, 0x71, 0xC7, 0x36, 0x43, 0xAD, 0xCE, 0x38,
      0x77, 0x37, 0x4A, 0xF2, 0x48, 0x2F, 0x38, 0x2B, 0x22, 0x27, 0x35, 0x5C, 0x3A, 0x6A, 0x21, 0x44,
      0xAA, 0x3F, 0x29, 0xA4, 0x3D, 0x69, 0xE1, 0xCF, 0x25, 0x4A, 0x25, 0x5E, 0x25, 0x3A, 0x4E, 0x41,
      0x4D, 0x7D, 0x22, 0x27, 0x4A, 0x21, 0x32, 0x2C, 0x21, 0x44, 0x38, 0x24, 0xCE, 0x42, 0x67, 0x37,
      0x33, 0x43, 0x44, 0xAC, 0x3B, 0x36, 0x4A, 0x62, 0x22, 0x27, 0x35, 0x7E, 0x45, 0x54, 0x21, 0x44,
      0x25, 0x2A, 0x25, 0x26, 0x25, 0x60, 0xC8, 0x3B, 0x36, 0x4A, 0x62, 0xB9, 0xEB, 0x1B, 0x7E, 0x89,
      0xB7, 0xB7, 0x8A, 0x3A, 0x50, 0x22, 0x27, 0x40, 0x45, 0x32, 0x2C, 0x21, 0x44, 0x33, 0x24, 0x34,
      0x5F, 0x1B, 0x7D, 0xCB, 0x34, 0x71, 0x40, 0x57, 0xCE, 0x35, 0x65, 0x42, 0x4E, 0x34, 0x64, 0x22,
      0x27, 0x40, 0x69, 0x4D, 0x55, 0x21, 0x44, 0x4C, 0x5A, 0xCE, 0x3B, 0x5E, 0xC7, 0x38, 0x24, 0x36,
      0x21, 0x4D, 0x5C);
    U(0x2605, 0x65E5, 0x672C, 0x5168, 0x56FD, 0x3067, 0x9A5A, 0x304D, 0x306E, 0x5149, 0x666F, 0x3092,
      0x767A, 0x898B, 0x25BC, 0x5BAE, 0x5D0E, 0x2026, 0x304A, 0x98DF, 0x3044, 0x521D, 0x3081, 0x306F,
      0x30CA, 0x30DE, 0x30BA, 0x6599, 0x7406, 0x25BC, 0x798F, 0x5CA1, 0x2026, 0x72AC, 0x306E, 0x5927,
      0x8ECD, 0x56E3, 0x304C, 0x6563, 0x6B69, 0x25BC, 0x4EAC, 0x90FD, 0x2026, 0x30AA, 0x30A6, 0x30E0,
      0x3068, 0x6563, 0x6B69, 0x3059, 0x308B, 0x0037, 0x0037, 0x6B73, 0x25BC, 0x9759, 0x5CA1, 0x2026,
      0x6D77, 0x5CB8, 0x306B, 0x5947, 0x8DE1, 0x306E, 0x7403, 0x4F53, 0x5CA9, 0x25BC, 0x5343, 0x8449,
      0x2026, 0x6728, 0x306E, 0x679D, 0x3067, 0x72AC, 0x4F9B, 0x990A);
    T(false);
}

#undef B
#undef U
#undef T


//----------------------------------------------------------------------------
// Encode test cases
//----------------------------------------------------------------------------

#define U(...) const ts::UString   u16({__VA_ARGS__})
#define B(...) const ts::ByteBlock b24({__VA_ARGS__})
#define T(success)             \
    debug() << std::endl;      \
    dump(u"Input:", u16);      \
    dump(u"Expected:", b24);   \
    const ts::ByteBlock enc(ts::ARIBCharset::B24.encoded(u16)); \
    dump(u"Encoded:", enc);    \
    ts::UString dec;           \
    const bool ok = ts::ARIBCharset::B24.decode(dec, enc.data(), enc.size()); \
    dump(u"Decoded:", dec);    \
    debug() << std::endl;      \
    TSUNIT_ASSERT(b24 == enc); \
    TSUNIT_EQUAL(success, ok); \
    TSUNIT_EQUAL(u16, dec)

void ARIBCharsetTest::testEncode1()
{
    U(0x004E, 0x0048, 0x004B, 0x7DCF, 0x5408, 0x0031, 0x30FB, 0x79CB, 0x7530);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x41, 0x6D, 0x39, 0x67, 0x1B, 0x7E, 0xB1, 0x21, 0x26, 0x3D, 0x29, 0x45, 0x44);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0x41, 0x6D, 0x39, 0x67, 0xB1, 0x21, 0x26, 0x3D, 0x29, 0x45, 0x44);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode2()
{
    U(0x004E, 0x0048, 0x004B, 0x7DCF, 0x5408, 0x0032, 0x30FB, 0x79CB, 0x7530);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x41, 0x6D, 0x39, 0x67, 0x1B, 0x7E, 0xB2, 0x21, 0x26, 0x3D, 0x29, 0x45, 0x44);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0x41, 0x6D, 0x39, 0x67, 0xB2, 0x21, 0x26, 0x3D, 0x29, 0x45, 0x44);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode3()
{
    U(0x004E, 0x0048, 0x004B, 0x643A, 0x5E2F, 0x0047, 0x30FB, 0x79CB, 0x7530);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x37, 0x48, 0x42, 0x53, 0x1B, 0x7E, 0xC7, 0x21, 0x26, 0x3D, 0x29, 0x45, 0x44);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0x37, 0x48, 0x42, 0x53, 0xC7, 0x21, 0x26, 0x3D, 0x29, 0x45, 0x44);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode4()
{
    U(0x004E, 0x0048, 0x004B, 0x0045, 0x30C6, 0x30EC, 0x0031, 0x79CB, 0x7530);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x45, 0x0F, 0x25, 0x46, 0x25, 0x6C, 0x1B, 0x7E, 0xB1, 0x3D, 0x29, 0x45, 0x44);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0xC5, 0x25, 0x46, 0x25, 0x6C, 0xB1, 0x3D, 0x29, 0x45, 0x44);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode5()
{
    U(0x004E, 0x0048, 0x004B, 0x0045, 0x30C6, 0x30EC, 0x0032, 0x79CB, 0x7530);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x45, 0x0F, 0x25, 0x46, 0x25, 0x6C, 0x1B, 0x7E, 0xB2, 0x3D, 0x29, 0x45, 0x44);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0xC5, 0x25, 0x46, 0x25, 0x6C, 0xB2, 0x3D, 0x29, 0x45, 0x44);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode6()
{
    U(0x004E, 0x0048, 0x004B, 0x0045, 0x30C6, 0x30EC, 0x0033, 0x79CB, 0x7530);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x45, 0x0F, 0x25, 0x46, 0x25, 0x6C, 0x1B, 0x7E, 0xB3, 0x3D, 0x29, 0x45, 0x44);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0xC5, 0x25, 0x46, 0x25, 0x6C, 0xB3, 0x3D, 0x29, 0x45, 0x44);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode7()
{
    U(0x004E, 0x0048, 0x004B, 0x643A, 0x5E2F, 0x0032);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x37, 0x48, 0x42, 0x53, 0x1B, 0x7E, 0xB2);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0x37, 0x48, 0x42, 0x53, 0xB2);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode8()
{
    U(0x79CB, 0x7530, 0x671D, 0x65E5, 0x653E, 0x9001);
    B(0x3D, 0x29, 0x45, 0x44, 0x44, 0x2B, 0x46, 0x7C, 0x4A, 0x7C, 0x41, 0x77);
    T(true);
}

void ARIBCharsetTest::testEncode9()
{
    U(0x0041, 0x0042, 0x0053, 0x79CB, 0x7530, 0x653E, 0x9001, 0x0031);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x42, 0x53, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x1B, 0x7E, 0xB1);
#else
    B(0x1B, 0x7E, 0xC1, 0xC2, 0xD3, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0xB1);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode10()
{
    U(0x0041, 0x0042, 0x0053, 0x79CB, 0x7530, 0x653E, 0x9001, 0x0032);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x42, 0x53, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x1B, 0x7E, 0xB2);
#else
    B(0x1B, 0x7E, 0xC1, 0xC2, 0xD3, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0xB2);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode11()
{
    U(0x79CB, 0x7530, 0x653E, 0x9001, 0x643A, 0x5E2F);
    B(0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x37, 0x48, 0x42, 0x53);
    T(true);
}

void ARIBCharsetTest::testEncode12()
{
    U(0x0041, 0x0042, 0x0053, 0x79CB, 0x7530, 0x653E, 0x9001, 0x81E8, 0x6642);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x42, 0x53, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x4E, 0x57, 0x3B, 0x7E);
#else
    B(0x1B, 0x7E, 0xC1, 0xC2, 0xD3, 0x3D, 0x29, 0x45, 0x44, 0x4A, 0x7C, 0x41, 0x77, 0x4E, 0x57, 0x3B, 0x7E);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode13()
{
    U(0x0041, 0x004B, 0x0054, 0x79CB, 0x7530, 0x30C6, 0x30EC, 0x30D3, 0x0031);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x25, 0x46, 0x25, 0x6C, 0x25, 0x53, 0x1B, 0x7E, 0xB1);
#else
    B(0x1B, 0x7E, 0xC1, 0xCB, 0xD4, 0x3D, 0x29, 0x45, 0x44, 0x25, 0x46, 0x25, 0x6C, 0x25, 0x53, 0xB1);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode14()
{
    U(0x0041, 0x004B, 0x0054, 0x79CB, 0x7530, 0x30C6, 0x30EC, 0x30D3, 0x0032);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x25, 0x46, 0x25, 0x6C, 0x25, 0x53, 0x1B, 0x7E, 0xB2);
#else
    B(0x1B, 0x7E, 0xC1, 0xCB, 0xD4, 0x3D, 0x29, 0x45, 0x44, 0x25, 0x46, 0x25, 0x6C, 0x25, 0x53, 0xB2);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode15()
{
    U(0x0041, 0x004B, 0x0054, 0x81E8, 0x6642);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x4E, 0x57, 0x3B, 0x7E);
#else
    B(0x1B, 0x7E, 0xC1, 0xCB, 0xD4, 0x4E, 0x57, 0x3B, 0x7E);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode16()
{
    U(0x0047, 0x30AC, 0x30A4, 0x30C9);
#if defined(GL_FIRST)
    B(0x0E, 0x47, 0x0F, 0x25, 0x2C, 0x25, 0x24, 0x25, 0x49);
#else
    B(0x1B, 0x7E, 0xC7, 0x25, 0x2C, 0x25, 0x24, 0x25, 0x49);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode17()
{
    U(0x0041, 0x004B, 0x0054, 0x79CB, 0x7530, 0x30C6, 0x30EC, 0x30D3);
#if defined(GL_FIRST)
    B(0x0E, 0x41, 0x4B, 0x54, 0x0F, 0x3D, 0x29, 0x45, 0x44, 0x25, 0x46, 0x25, 0x6C, 0x25, 0x53);
#else
    B(0x1B, 0x7E, 0xC1, 0xCB, 0xD4, 0x3D, 0x29, 0x45, 0x44, 0x25, 0x46, 0x25, 0x6C, 0x25, 0x53);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode18()
{
    U(0x004E, 0x0048, 0x004B, 0x30CB, 0x30E5, 0x30FC, 0x30B9, 0x0037, 0xD83C, 0xDE14, 0xD83C, 0xDE11);
#if defined(GL_FIRST)
    B(0x0E, 0x4E, 0x48, 0x4B, 0x0F, 0x25, 0x4B, 0x25, 0x65, 0x21, 0x3C, 0x25, 0x39, 0x1B, 0x7E, 0xB7, 0x7A, 0x5A, 0x7A, 0x56);
#else
    B(0x1B, 0x7E, 0xCE, 0xC8, 0xCB, 0x25, 0x4B, 0x25, 0x65, 0x21, 0x3C, 0x25, 0x39, 0xB7, 0x7A, 0x5A, 0x7A, 0x56);
#endif
    T(true);
}

void ARIBCharsetTest::testEncode19()
{
    U(0x591C, 0x0037, 0x6642, 0x3001, 0x300C, 0x4E00, 0x6B69, 0x5148, 0x3078, 0x3001, 0x4E00, 0x6B69,
      0x6DF1, 0x304F, 0x300D, 0x3000, 0x4ECA, 0x3001, 0x3053, 0x306E, 0x30CB, 0x30E5, 0x30FC, 0x30B9,
      0x3092, 0x5C4A, 0x3051, 0x305F, 0x3044, 0x3000, 0x3010, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC,
      0x3011, 0x9752, 0x4E95, 0x5B9F, 0xFF0C, 0x3010, 0x30B5, 0x30D6, 0x30AD, 0x30E3, 0x30B9, 0x30BF,
      0x30FC, 0x3011, 0x6C60, 0x7530, 0x4F38, 0x5B50, 0xFF0C, 0x4F0A, 0x85E4, 0x6D77, 0x5F66, 0xFF0C,
      0x3010, 0x6C17, 0x8C61, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC, 0x3011, 0x4E2D, 0x6751, 0x7F8E,
      0x516C);
    B(0x4C, 0x6B, 0x1B, 0x7E, 0xB7, 0x3B, 0x7E, 0x21, 0x22, 0x21, 0x56, 0x30, 0x6C, 0x4A, 0x62, 0x40,
      0x68, 0x24, 0x58, 0x21, 0x22, 0x30, 0x6C, 0x4A, 0x62, 0x3F, 0x3C, 0x24, 0x2F, 0x21, 0x57, 0x21,
      0x21, 0x3A, 0x23, 0x21, 0x22, 0x24, 0x33, 0x24, 0x4E, 0x25, 0x4B, 0x25, 0x65, 0x21, 0x3C, 0x25,
      0x39, 0x24, 0x72, 0x46, 0x4F, 0x24, 0x31, 0x24, 0x3F, 0x24, 0x24, 0x21, 0x21, 0x21, 0x5A, 0x25,
      0x2D, 0x25, 0x63, 0x25, 0x39, 0x25, 0x3F, 0x21, 0x3C, 0x21, 0x5B, 0x40, 0x44, 0x30, 0x66, 0x3C,
      0x42, 0x21, 0x24, 0x21, 0x5A, 0x25, 0x35, 0x25, 0x56, 0x25, 0x2D, 0x25, 0x63, 0x25, 0x39, 0x25,
      0x3F, 0x21, 0x3C, 0x21, 0x5B, 0x43, 0x53, 0x45, 0x44, 0x3F, 0x2D, 0x3B, 0x52, 0x21, 0x24, 0x30,
      0x4B, 0x46, 0x23, 0x33, 0x24, 0x49, 0x27, 0x21, 0x24, 0x21, 0x5A, 0x35, 0x24, 0x3E, 0x5D, 0x25,
      0x2D, 0x25, 0x63, 0x25, 0x39, 0x25, 0x3F, 0x21, 0x3C, 0x21, 0x5B, 0x43, 0x66, 0x42, 0x3C, 0x48,
      0x7E, 0x38, 0x78);
    T(true);
}

void ARIBCharsetTest::testEncode20()
{
    U(0x51FA, 0x6F14, 0x8005);
    B(0x3D, 0x50, 0x31, 0x69, 0x3C, 0x54);
    T(true);
}

void ARIBCharsetTest::testEncode21()
{
    U(0x3010, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC, 0x3011, 0x9752, 0x4E95, 0x5B9F, 0xFF0C, 0x3010,
      0x30B5, 0x30D6, 0x30AD, 0x30E3, 0x30B9, 0x30BF, 0x30FC, 0x3011, 0x6C60, 0x7530, 0x4F38, 0x5B50,
      0xFF0C, 0x4F0A, 0x85E4, 0x6D77, 0x5F66, 0xFF0C, 0x3010, 0x6C17, 0x8C61, 0x30AD, 0x30E3, 0x30B9,
      0x30BF, 0x30FC, 0x3011, 0x4E2D, 0x6751, 0x7F8E, 0x516C);
    B(0x21, 0x5A, 0x25, 0x2D, 0x25, 0x63, 0x25, 0x39, 0x25, 0x3F, 0x21, 0x3C, 0x21, 0x5B, 0x40, 0x44,
      0x30, 0x66, 0x3C, 0x42, 0x21, 0x24, 0x21, 0x5A, 0x25, 0x35, 0x25, 0x56, 0x25, 0x2D, 0x25, 0x63,
      0x25, 0x39, 0x25, 0x3F, 0x21, 0x3C, 0x21, 0x5B, 0x43, 0x53, 0x45, 0x44, 0x3F, 0x2D, 0x3B, 0x52,
      0x21, 0x24, 0x30, 0x4B, 0x46, 0x23, 0x33, 0x24, 0x49, 0x27, 0x21, 0x24, 0x21, 0x5A, 0x35, 0x24,
      0x3E, 0x5D, 0x25, 0x2D, 0x25, 0x63, 0x25, 0x39, 0x25, 0x3F, 0x21, 0x3C, 0x21, 0x5B, 0x43, 0x66,
      0x42, 0x3C, 0x48, 0x7E, 0x38, 0x78);
    T(true);
}

void ARIBCharsetTest::testEncode22()
{
    U(0x30C0, 0x30FC, 0x30A6, 0x30A3, 0x30F3, 0x304C, 0x6765, 0x305F, 0xFF01, 0x300C, 0x6CE2, 0x4E71,
      0x306E, 0x30E9, 0x30A4, 0x30AA, 0x30F3, 0x5B66, 0x5712, 0x306B, 0x6F5C, 0x5165, 0xFF01, 0x767E,
      0x7363, 0x306E, 0x738B, 0x3092, 0x990A, 0x6210, 0xFF01, 0xFF01, 0x300D, 0xD83C, 0xDE16, 0xD83C,
      0xDE11);
    B(0x25, 0x40, 0x21, 0x3C, 0x25, 0x26, 0x25, 0x23, 0x25, 0x73, 0x24, 0x2C, 0x4D, 0x68, 0x24, 0x3F,
      0x21, 0x2A, 0x21, 0x56, 0x47, 0x48, 0x4D, 0x70, 0x24, 0x4E, 0x25, 0x69, 0x25, 0x24, 0x25, 0x2A,
      0x25, 0x73, 0x33, 0x58, 0x31, 0x60, 0x24, 0x4B, 0x40, 0x78, 0x46, 0x7E, 0x21, 0x2A, 0x49, 0x34,
      0x3D, 0x43, 0x24, 0x4E, 0x32, 0x26, 0x24, 0x72, 0x4D, 0x5C, 0x40, 0x2E, 0x21, 0x2A, 0x21, 0x2A,
      0x21, 0x57, 0x7A, 0x5C, 0x7A, 0x56);
    T(true);
}

void ARIBCharsetTest::testEncode23()
{
    U(0x6210, 0x9577, 0x307E, 0x3063, 0x305F, 0x3060, 0x4E2D, 0x306E, 0x30E9, 0x30A4, 0x30AA, 0x30F3,
      0x306E, 0x5B50, 0x3069, 0x3082, 0x305F, 0x3061, 0x304C, 0x3001, 0x7FA4, 0x308C, 0x306E, 0x4E2D,
      0x3067, 0x5148, 0x751F, 0x5F79, 0x306E, 0x5927, 0x4EBA, 0x304B, 0x3089, 0x72E9, 0x308A, 0x306E,
      0x6280, 0x3084, 0x5B50, 0x80B2, 0x3066, 0x8853, 0x3092, 0x5B66, 0x3076, 0x3002, 0x4E0D, 0x771F,
      0x9762, 0x76EE, 0x306A, 0x751F, 0x5F92, 0x306F, 0x9000, 0x5B66, 0x51E6, 0x5206, 0x306B, 0xFF01,
      0xFF1F, 0x5B66, 0x5712, 0x30C9, 0x30E9, 0x30DE, 0x9854, 0x8CA0, 0x3051, 0x306E, 0x6CE2, 0x4E71,
      0x306E, 0x65E5, 0x3005, 0x306B, 0x5BC6, 0x7740, 0xFF01);
    B(0x40, 0x2E, 0x44, 0x39, 0x24, 0x5E, 0x24, 0x43, 0x24, 0x3F, 0x24, 0x40, 0x43, 0x66, 0x24, 0x4E,
      0x25, 0x69, 0x25, 0x24, 0x25, 0x2A, 0x25, 0x73, 0x24, 0x4E, 0x3B, 0x52, 0x24, 0x49, 0x24, 0x62,
      0x24, 0x3F, 0x24, 0x41, 0x24, 0x2C, 0x21, 0x22, 0x37, 0x32, 0x24, 0x6C, 0x24, 0x4E, 0x43, 0x66,
      0x24, 0x47, 0x40, 0x68, 0x40, 0x38, 0x4C, 0x72, 0x24, 0x4E, 0x42, 0x67, 0x3F, 0x4D, 0x24, 0x2B,
      0x24, 0x69, 0x3C, 0x6D, 0x24, 0x6A, 0x24, 0x4E, 0x35, 0x3B, 0x24, 0x64, 0x3B, 0x52, 0x30, 0x69,
      0x24, 0x46, 0x3D, 0x51, 0x24, 0x72, 0x33, 0x58, 0x24, 0x56, 0x21, 0x23, 0x49, 0x54, 0x3F, 0x3F,
      0x4C, 0x4C, 0x4C, 0x5C, 0x24, 0x4A, 0x40, 0x38, 0x45, 0x4C, 0x24, 0x4F, 0x42, 0x60, 0x33, 0x58,
      0x3D, 0x68, 0x4A, 0x2C, 0x24, 0x4B, 0x21, 0x2A, 0x21, 0x29, 0x33, 0x58, 0x31, 0x60, 0x25, 0x49,
      0x25, 0x69, 0x25, 0x5E, 0x34, 0x69, 0x49, 0x69, 0x24, 0x31, 0x24, 0x4E, 0x47, 0x48, 0x4D, 0x70,
      0x24, 0x4E, 0x46, 0x7C, 0x21, 0x39, 0x24, 0x4B, 0x4C, 0x29, 0x43, 0x65, 0x21, 0x2A);
    T(true);
}

void ARIBCharsetTest::testEncode24()
{
    U(0x3010, 0x571F, 0x66DC, 0x6642, 0x4EE3, 0x30C9, 0x30E9, 0x30DE, 0x3011, 0x96F2, 0x9727, 0x4EC1,
      0x5DE6, 0x885B, 0x9580, 0x0033, 0x3000, 0xD83C, 0xDE1F, 0xFF08, 0x0031, 0xFF09, 0x300C, 0x5D50,
      0x306E, 0x4E88, 0x611F, 0x300D, 0xD83C, 0xDE16, 0xD83C, 0xDE11);
    B(0x21, 0x5A, 0x45, 0x5A, 0x4D, 0x4B, 0x3B, 0x7E, 0x42, 0x65, 0x25, 0x49, 0x25, 0x69, 0x25, 0x5E,
      0x21, 0x5B, 0x31, 0x40, 0x4C, 0x38, 0x3F, 0x4E, 0x3A, 0x38, 0x31, 0x52, 0x4C, 0x67, 0x1B, 0x7E,
      0xB3, 0x21, 0x21, 0x7A, 0x6B, 0x21, 0x4A, 0xB1, 0x21, 0x4B, 0x21, 0x56, 0x4D, 0x72, 0x24, 0x4E,
      0x4D, 0x3D, 0x34, 0x36, 0x21, 0x57, 0x7A, 0x5C, 0x7A, 0x56);
    T(true);
}

void ARIBCharsetTest::testEncode25()
{
    U(0x0061, 0x0062, 0x0020, 0x0063, 0x9A5A, 0x304D, 0x3000, 0x306E, 0x6563);
#if defined(GL_FIRST)
    B(0x0E, 0x61, 0x62, 0x20, 0x63, 0x0F, 0x36, 0x43, 0x24, 0x2D, 0x21, 0x21, 0x24, 0x4E, 0x3B, 0x36);
#else
    B(0x1B, 0x7E, 0xE1, 0xE2, 0xA0, 0xE3, 0x36, 0x43, 0x24, 0x2D, 0x21, 0x21, 0x24, 0x4E, 0x3B, 0x36);
#endif
    T(true);
}

#undef B
#undef U
#undef T
